#include "thread_pool.h"
#include "tcp_conn.h"

// 一旦有task消息过来，这个业务是处理task消息业务的主流程
// 只要有人调用 thread_queue:: send()方法就会触发次函数
void deal_task(event_loop* loop, int fd, void *args){
    
    thread_queue<task_msg> *queue = (thread_queue<task_msg>*)args;
    // 1.从thread_queue中取数据
    std::queue<task_msg> new_queue;
    queue->recv(new_queue);   // 此时的new_queue就存放了全部的任务
    
    // 依次处理每个任务
    while(new_queue.empty() != true){
        // 从队列中得到一个任务
        task_msg task = new_queue.front();

        // 将这个任务从任务队列弹出
        new_queue.pop();

        // 2.判断任务类型
        if(task.type == task_msg::NEW_CONN){
            // 如果是任务1，则当前线程创建新的链接，并将这个connfd加入到当前线程的event_loop中
            tcp_conn * conn = new tcp_conn(task.connfd, loop);
            if(conn==NULL){
                fprintf(stderr,"in thread new tcp_conn error\n");
                exit(1);
            }

            printf("thread:create net connection success!\n");

        }
        else if(task.type == task_msg::NEW_TASK){
            // 如果是任务2，则是一个普通任务，将任务添加到loop的task中
            loop->add_task(task.task_cb, task.args);

        }
        else{
             //其他未识别任务
             fprintf(stderr, "unknow task!\n");
        }
        
    }

    

}

// 线程调用的主函数
void* thread_main(void* args){
    thread_queue<task_msg> *queue = (thread_queue<task_msg>*)args;

    //  每个线程都应该有一个event_loop来监控客户端链接的读写事件
    event_loop* loop = new event_loop();
    if(loop == NULL){
        perror("thread_main new event_loop error");
        exit(1);
    }

    //注册一个触发消息任务读写的callback函数 
    queue->set_loop(loop);
    queue->set_callback(deal_task, queue);

    // 启动阻塞监听
    loop->event_process();

    return NULL;

}

// 构造函数，初始化线程池，开辟thread_cnt个，每次创建一个server就应该创建一个线程池(应该是单例模式)
thread_pool::thread_pool(int thread_cnt){
    _index = 0;
    _queues = NULL;
    _thread_cnt = thread_cnt;
    if(_thread_cnt <= 0){
        fprintf(stderr, "thread_cnt need > 0 \n");
        exit(1);
    }

    // 创建_thread_cnt个任务队列thread_queue
    _queues = new thread_queue<task_msg>* [_thread_cnt];

    // 创建_thread_cnt个线程
    _tids = new pthread_t[_thread_cnt];

    // 开辟线程
    int ret;
    for(int i=0; i<_thread_cnt; i++){
        //给当前线程创建一个任务消息队列
        _queues[i] = new thread_queue<task_msg>();

        // 第i个线程绑定第i个thread_queue
        ret = pthread_create(&_tids[i], NULL, thread_main, _queues[i]);
        if(ret == -1){
            fprintf(stderr, "pthread_create error \n");
            exit(1);
        }

        // 将线程分离，使得主线程和子线程脱离关系
        pthread_detach(_tids[i]);

        printf("new thread:%d success!\n", i+1);
    }
}

//  获取一个thead
thread_queue<task_msg>* thread_pool::get_thread(){
    if (_index == _thread_cnt) {
        _index = 0; 
    }
    printf("index: %d\n", _index);
    return _queues[_index++];
}

// 析构函数
thread_pool::~thread_pool(){

}


// 发送一个NEW_TASK任务给所有的线程
void thread_pool::send_task(task_func func, void* args){
    
    // 制作一个任务
    task_msg task;
    task.type = task_msg::NEW_TASK;
    task.task_cb = func;
    task.args = args;

    // 给当前所有在线的线程中的thread_queue都发送该任务
    for(int i=0; i<_thread_cnt; i++){
        // 取出第i个线程
        thread_queue<task_msg>* queue = _queues[i];
        // 给每个线程发一个task任务
        queue->send(task);
    }

}